import logging
import os
from logging.handlers import TimedRotatingFileHandler
from pythonjsonlogger import jsonlogger
from typing import Optional
log_type = "json"
log_dir = "logs"

class LoggerFactory:
    _instance = None
    _loggers = {}

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super(LoggerFactory, cls).__new__(cls)
        return cls._instance

    @staticmethod
    def get_logger(name: Optional[str] = None,
                   log_dir: str = "logs") -> logging.Logger:
        """
        获取或创建logger实例
        :param name: logger名称
        :param log_dir: 日志目录
        :return: logger实例
        """
        logger_name = name or __name__
        # 仅通过_loggers字典判断是否已存在，避免重复检查handlers
        if logger_name in LoggerFactory._loggers:
            return LoggerFactory._loggers[logger_name]

        logger = logging.getLogger(logger_name)
        # 原代码中对logger.handlers的检查可删除（因为_loggers已确保唯一性）
        # 原代码：
        # if logger.handlers:
        #     return logger

        # 避免重复添加处理器
        if logger.handlers:
            return logger

        # 确保日志目录存在（添加异常处理）
        try:
            if not os.path.exists(log_dir):
                os.makedirs(log_dir, exist_ok=True)  # exist_ok避免目录已存在时的异常
        except OSError as e:
            logger.error(f"创建日志目录 {log_dir} 失败: {str(e)}")
            raise  # 或根据需求处理，如终止程序

        # 定义日志级别配置
        # 从环境变量解析日志级别配置（格式示例：DEBUG:7,INFO:30,WARNING:30,ERROR:90）
        log_levels_env = os.getenv("LOG_LEVELS", "debug:7,info:30,warning:30,error:90")
        log_levels = {}
        for item in log_levels_env.split(","):
            level_name, backup_count = item.split(":")
            log_levels[level_name] = (
                getattr(logging, level_name.upper()),  # 动态获取日志级别
                int(backup_count)
            )

        # 原硬编码部分删除，替换为上述动态解析代码
        # 原代码：
        # log_levels = {
        #     'debug': (logging.DEBUG, 7),
        #     'info': (logging.INFO, 30),
        #     'warning': (logging.WARNING, 30),
        #     'error': (logging.ERROR, 90)
        # }
        logger.setLevel(logging.INFO)

        # 创建格式化器
        fmt='%(asctime)s %(levelname)s %(filename)s %(lineno)d %(message)s'
        datefmt = '%Y-%m-%d %H:%M:%S'
        if log_type == 'json':
            formatter = jsonlogger.JsonFormatter(
                fmt=fmt,
                datefmt=datefmt,
                json_ensure_ascii=False)
        else:
            formatter = logging.Formatter(
                fmt=fmt,
                datefmt=datefmt)

        # 为每个级别创建处理器
        for level_name, (level, backup_count) in log_levels.items():
            # 原有按天切割的处理器
            file_handler = TimedRotatingFileHandler(filename=os.path.join(
                log_dir, f'app_{level_name}.log'),
                when='midnight',
                interval=10,
                backupCount=18, # 保留最近180天的日志
                encoding='utf-8')
            file_handler.setLevel(level)
            file_handler.setFormatter(formatter)
            logger.addHandler(file_handler)

            # 新增保留所有日志的处理器（不切割，始终追加）
            all_log_handler = logging.FileHandler(
                filename=os.path.join(log_dir, f'app_{level_name}_all.log'),  # 文件名添加_all标识
                mode='a',  # 追加模式（默认即为'a'，可省略）
                encoding='utf-8'
            )
            all_log_handler.setLevel(level)
            all_log_handler.setFormatter(formatter)
            logger.addHandler(all_log_handler)

        # 添加控制台处理器
        console_handler = logging.StreamHandler()
        console_handler.setLevel(logging.INFO)
        console_handler.setFormatter(
            logging.Formatter(
                '%(asctime)s|%(levelname)-5s|%(filename)s:%(lineno)d|%(message)s',
                datefmt='%Y-%m-%d %H:%M:%S'))
        logger.addHandler(console_handler)

        LoggerFactory._loggers[logger_name] = logger
        return logger


def setup_logger(
    name: Optional[str] = None,
    log_dir: str = log_dir
) -> logging.Logger:
    """
    设置并返回logger实例的便捷函数
    """

    return LoggerFactory().get_logger(name, log_dir)


# logger = setup_logger()
